序言
在企业环境中,众多部门各自开发的认证系统,对用户来说,如果每个系统都需要独立登录,无疑增加了使用的复杂性。因此,如果有一把“万能钥匙”,能够让用户无需重复登录,直接访问每个系统,那将大大提升效率和用户体验。
而本文要介绍的 SSO 就像一把万能钥匙,系统接入 SSO 后,用户只需登录一次,就可以访问所有系统,极大地简化了用户的操作步骤,提高了工作效率。
SSO 简介
单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次 就可以访问所有相互信任的应用系统。
体系架构

在一个 SSO 系统里,一般会定义两类角色:
- Service Provider:简称SP ,登录信息的消费者,一般指Web应用。当用户访问 SP时,SP会检查用户是否已经登录。如果用户没有登录,SP 会将用户重定向到IDP 进行认证
- Identity Provider:简称 IDP,负责提供登录信息,甩于对用户进行认证,亦称认证中中心。当用户首次登录时,IDP会要求用户输入用户名秘密码。如果认证成功,IDP 会生成一个包含用户身份信息的凭证,并将用户重定向回 SP。SP 可以通过这个凭证来验证用户的身份
如上图流程说明,SSO 实现模式一般包括以下三个原则:
- ① 所有的认证登录都在 SSO 认证中心进行;
- ② SSO 认证中心通过一些凭证来告诉 Web 应用当前访问用户究竟是不是已通过认证的用户;
- ③ SSO 认证中心和所有的 Web 应用建立一种信任关系,也就是说 web 应用必须信任认证中心
SSO 实现
SSO 的实现一般有 CAS 和 OAuth2 两种:

CAS 和 OAuth2 都可以用于实现 SSO,但它们的重点和实现方式略有不同。
CAS 专注于提供统一登录服务,一般用于企业内部统一各个子系统的登录,而OAuth2 则更关注授权方面的问题,一般第三方系统统一外部登录。
Oauth2

Oauth2 一般应用在各种社交应用的登录中,以 Google 为例,其交互流程如下:
1、访问 Client,Clilent 把用户redirect 到 Google(带着 SP 的信息)
2、用户登录Google(如果已登陆,这一步可以跳过)
3、Google 把用户redirect回Clilent(带着一个授权码code )
4、Clilent 用这个授权码在后台向Google 换取 AccessToken,根据此 Token 可获取用户的信息(唯一ID、email之类的)
5、Clilent根据从Google获得的用户信息让用户继续使用。
CAS
CAS 包括两部分:
- CAS Server:负责完成对用户的认证工作 , 需要独立部署 , CAS Server 会处理用户名 / 密码等凭证
- CAS Client :负责处理对客户端受保护资源的访问请求,需要对请求方进行身份认证时,重定向到 CAS Server 进行认证。(原则上,客户端应用不再接受任何的用户名密码等 Credentials )。CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源。
流程步骤
基础模式 SSO 访问流程主要有以下步骤:
- 访问服务: SSO 客户端发送请求访问应用系统提供的服务资源。
- 定向认证: SSO 客户端会重定向用户请求到 SSO 服务器。
- 用户认证:用户身份认证
- 发放票据: SSO 服务器会产生一个随机的 Service Ticket
- 验证票据: SSO 服务器验证票据 Service Ticket 的合法性,验证通过后,允许客户端访问服务
- 传输用户信息: SSO 服务器验证票据通过后,传输用户认证结果信息给客户端
简化流程

1.用户通过浏览器访问应用1,应用1发现用户没有登录,于是携带上一个service参数进行重定向,让用户去CAS Server上登录。
2.浏览器自动重定向到CAS Server上,CAS Server获取用户Cookie中携带的TGC, 去校验用户是否已经登录
a. 如果未登录,则重定向到CASServer的登录页面,用户输入用户名/密码,CAS
Server会生成票据TGT,并且根据TGT签发一个票据ST,再将TGC放在用户的Cookie中,完成身份校验
b.如果已经登录,则完成身份校验(此时CASServer可以根据用户的TGC找到TGT,进而获取用户的信息)
3.CASServer完成身份校验之后,会将ST拼接在service中,302重定向返回应用 1。此过程中浏览器将首先将TGC存在Cookie中,然后携带上ST重定向到应用1。4.应用1收到浏览器传来的S之后,拿去CASServer上校验,去判断用户的登录状态,如果用户登录合法,CAS Server就会返回用户信息给应用1。
5.浏览器再去访问应用2,应用2发现用户未登录,重定向到CASServer。
6.CASServer发现此时用户实际上已经登录了,于是又重定向回应用2,同时携带上ST。
7.应用2根据ST去CASServer上校验,获取用户的登录信息。
票据相关概念
在CAS认证成功后,会生成三种类型的票据:

- TGT:全称Ticket Granting Ticket,相当于应用端的IttpSession,用户登录成功后,用户的基本信息,如用户名、登录有效期等信息,都将存储在此。
- TGC:全称Ticket Granting Cookie
- TGC中存储了用于后续服务票据获取的凭证信息,以便用户在同一会话中访问多个服务而无需重新认证
- TGC以Cookie的形式保存在浏览器中,通常主域名下,比如example.com。Cookip name为TGC,value为TGT,CAS Server可以根据TGC可以拿到TGT以确定对应用户
- ST:全称Service Ticket,ST是CAS Sever发放给用户的一张票据,用户在访问其他服务时,发现没有Cookie或者ST,那么就会302重定向到CAS Server获取ST,然后会携带着ST302重定向回来,CASC1ient则通过ST去CAS Server上获取用户的登录状态。之后子系统根据ST校验用户是否存在系统中,用户可以根据ST与CASServer交互获取用户信息,最后构建自己系统的权限信息,ST一次用完后,用户构建自己的用户信息,将不走Ticket拦截器
完整流程

上图流程简单说明:
- 用户通过浏览器访问应用1,应用1 发现用户没有登录,于是返回 302,并且携带上一个 service 参数,让用户去 CAS Server 上登录。
- 浏览器自动重定向到 CAS Server 上,CAS Server 获取用户 Cookie 中携带的 TGC,去校验用户是否已经登录,如果已经登录,则完成身份校验(此时 CAS Server 可以根据用户的 TGC 找到 TGT,进而获取用户的信息);如果未登录,则重定向到 CAS Server 的登录页面,用户输入用户名/密码,CAS Server 会生成 TGT,并且根据 TGT 签发一个 ST,再将 TGC 放在用户的 Cookie 中,完成身份校验。
- CAS Server 完成身份校验之后,会将 ST 拼接在 service 中,返回 302,浏览器将首先将 TGC 存在 Cookie 中,然后根据 302 的指示,携带上 ST 重定向到应用1。
- 应用1 收到浏览器传来的 ST 之后,拿去 CAS Server 上校验,去判断用户的登录状态,如果用户登录合法,CAS Server 就会返回用户信息给 应用1。
- 浏览器再去访问应用2,应用2 发现用户未登录,重定向到 CAS Server。
- CAS Server 发现此时用户实际上已经登录了,于是又重定向回应用2,同时携带上 ST。
- 应用2 拿着 ST 去 CAS Server 上校验,获取用户的登录信息。
在整个登录过程中,浏览器分别和 CAS Server、应用1、应用2 建立了会话,其中,和 CAS Server 建立的会话称之为全局会话,和应用1、应用2 建立的会话称之为局部会话;一旦局部会话成功建立,以后用户再去访问应用1、应用2 就不会经过 CAS Server 了。
其他流程图

CAS 安全
CAS 的安全性仅仅依赖于 SSL 。使用的是 secure cookie 。
TGC 安全
对于一个 CAS 用户来说,最重要是要保护它的 TGC ,如果 TGC 不慎被 CAS Server 以外的实体获得, Hacker 能够找到该 TGC ,然后冒充 CAS 用户访问 所有 授权资源。 PGT 的角色跟 TGC 是一样的。
从基础模式可以看出, TGC 是 CAS Server 通过 SSL 方式发送给终端用户,因此,要截取 TGC 难度非常大,从而确保 CAS 的安全性。
TGT 的存活周期默认为 120 分钟。
ST 安全性
ST ( Service Ticket )是通过 Http 传送的,因此网络中的其他人可以 Sniffer 到其他人的 Ticket 。 CAS 通过以下几方面来使 ST 变得更加安全(事实上都是可以配置的):
- ST 只能使用一次:CAS 协议规定,无论 Service Ticket 验证是否成功, CAS Server 都会清除服务端缓存中的该Ticket ,从而可以确保一个 Service Ticket 不被使用两次。
- ST 在一段时间内失效:CAS 规定 ST 只能存活一定的时间,然后 CAS Server 会让它失效。默认有效时间为 5 分钟。
- ST 基于随机数生成:ST 必须足够随机,如果 ST 生成规则被猜出, Hacker 就等于绕过 CAS 认证,直接访问对应的服务,因此 ST 是基于随机数生成的